/** 
  Copyright (c) 2008, 2009 Claudio Imbrenda
  This program is released under the terms of the
  GNU GPL version 3 or later.
*/


package interfaccia;
import java.io.*;
import java.util.Vector;
import javax.swing.*;
import macchina.*;
import java.awt.Font;
import java.util.ResourceBundle;

import static macchina.MRUtils.*;

/**
 *
 * @author  Claudio Imbrenda
 */
public class MRTeletypePanel extends JPanel implements RegistroUscita {
      
  private static ResourceBundle bundle_interfaccia = 
          ResourceBundle.getBundle("interfaccia/Bundle_interfaccia");  
  
     
  private Vector<Byte> chars = new Vector<Byte>(1024);
  
  private String[] separators = {
    "\n",",",";"," ","\t",""
  };
  
  public static final int NEWLINE_SEP=0;
  public static final int COMMA_SEP=1;
  public static final int SEMICOLON_SEP=2;
  public static final int SPACE_SEP=3;
  public static final int TAB_SEP=4;
  public static final int NOTHING_SEP=5;
  
  public static final int HISTORICAL_TTY=0;
  public static final int ASCII_TTY=1;
  public static final int BASE2_TTY=2;
  public static final int BASE8_TTY=3;
  public static final int BASE10_TTY=4;
  public static final int BASE16_TTY=5;

  public static final int TTYWIDTH = 80;
  
  private int cursep=5;
  private int curmode;

  private boolean hassound=false;
  
  private boolean ltrs=false;
  private int linelen=0;
  private boolean classic=false;

  private Macchina m=null;

  /** Creates new form MRTeletypePanel */
  public MRTeletypePanel(Macchina ma) {
    initComponents();
    m=ma;
    txtaTeletypeOutput.setFont(new Font("Courier", Font.PLAIN, 12));
  }

  public MRTeletypePanel(){
      this(null);
  }

  public MRTeletypePanel(Macchina ma, boolean classica){
      this(ma);
      jLabel1.setVisible(false);
      jLabel2.setVisible(false);
      comboDisplay.setVisible(false);
      comboSeparator.setVisible(false);
      classic=classica;
  }
  
  
  /** This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    jPanel1 = new javax.swing.JPanel();
    btnClear = new javax.swing.JButton();
    jLabel5 = new javax.swing.JLabel();
    jLabel1 = new javax.swing.JLabel();
    comboDisplay = new javax.swing.JComboBox();
    jLabel4 = new javax.swing.JLabel();
    jLabel2 = new javax.swing.JLabel();
    comboSeparator = new javax.swing.JComboBox();
    jScrollPane1 = new javax.swing.JScrollPane();
    txtaTeletypeOutput = new javax.swing.JTextArea();

    setLayout(new java.awt.BorderLayout());

    jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.X_AXIS));

    btnClear.setText(bundle_interfaccia.getString("Pulisci")); // NOI18N
    btnClear.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        btnClearActionPerformed(evt);
      }
    });
    jPanel1.add(btnClear);

    jLabel5.setText("   ");
    jPanel1.add(jLabel5);

    jLabel1.setLabelFor(comboDisplay);
    jLabel1.setText(bundle_interfaccia.getString("Visualizzazione:")); // NOI18N
    jPanel1.add(jLabel1);

    comboDisplay.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Storica", "Caratteri ASCII", "Base 2", "Base 8", "Interi", "Base 16" }));
    comboDisplay.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        comboDisplayActionPerformed(evt);
      }
    });
    jPanel1.add(comboDisplay);

    jLabel4.setText("  ");
    jPanel1.add(jLabel4);

    jLabel2.setLabelFor(comboSeparator);
    jLabel2.setText(bundle_interfaccia.getString("Separatore:")); // NOI18N
    jPanel1.add(jLabel2);

    comboSeparator.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "A capo", "Virgola", "Punto e virgola", "Spazio", "Tab" }));
    comboSeparator.setEnabled(false);
    comboSeparator.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        comboSeparatorActionPerformed(evt);
      }
    });
    jPanel1.add(comboSeparator);

    add(jPanel1, java.awt.BorderLayout.PAGE_START);

    txtaTeletypeOutput.setColumns(80);
    txtaTeletypeOutput.setEditable(false);
    txtaTeletypeOutput.setMargin(new java.awt.Insets(6, 6, 6, 0));
    jScrollPane1.setViewportView(txtaTeletypeOutput);

    add(jScrollPane1, java.awt.BorderLayout.CENTER);
  }// </editor-fold>//GEN-END:initComponents

    private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearActionPerformed
        txtaTeletypeOutput.setText("");
        chars.clear();
        linelen=0;
}//GEN-LAST:event_btnClearActionPerformed

    private void comboDisplayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboDisplayActionPerformed
        int newmode=comboDisplay.getSelectedIndex();
        if(newmode==curmode)return;
        curmode=newmode;

        if(curmode==HISTORICAL_TTY){
            comboSeparator.setEnabled(false);
            cursep=NOTHING_SEP;
        }else{
            comboSeparator.setEnabled(true);
            cursep=comboSeparator.getSelectedIndex();
        }
        rerenderall();
}//GEN-LAST:event_comboDisplayActionPerformed

    private void comboSeparatorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboSeparatorActionPerformed
        int newsep = comboSeparator.getSelectedIndex();
        if(newsep==cursep)return;
        cursep=comboSeparator.getSelectedIndex();
        rerenderall();
}//GEN-LAST:event_comboSeparatorActionPerformed

    
  public void write(byte w) {
    w=(byte)(w&Macchina.CINQUE);
    txtaTeletypeOutput.append(rendersingle(w, chars.isEmpty()));
    chars.add(w);
  }
  
  private void rerenderall(){
      boolean first=true;
      boolean tmpsnd = hassound;

      hassound=false;
      linelen=0;
      txtaTeletypeOutput.setText("");
      if(chars.isEmpty())return;
      ltrs=false;
      
      for(byte b:chars){
        txtaTeletypeOutput.append(rendersingle(b, first));
        first=false;
      }
      hassound=tmpsnd;
  }
  
  /**
   * Saves the output of the teletype.
   * @param dest an instance of RegistroUscita. Will be used to write the
   * output of the teletype.
   */
  public void save(RegistroUscita dest){
      for(byte b:chars){
          dest.write(b);
      }
  }
  
  public void saveText(File f) throws IOException{
      (new FileWriter(f)).write(txtaTeletypeOutput.getText());
  }


  public void setSoundEnabled(boolean v){
      hassound=v;
  }

  public boolean isSoundEnabled(){
      return hassound;
  }

  private String rendersingle(byte w, boolean first){
      String res;
      
      if(!first)
          res=separators[cursep];
      else 
          res="";
      
      if(w==31)
          ltrs=true;
      else if(w==27)
          ltrs=false;
      
      switch(curmode){
          case HISTORICAL_TTY:
              char a = toHistorical(w,ltrs);
              if(a=='\n'){
                  res+=a;
                  linelen=0;
              }else if(a=='\r'){
                  res+=a;
              }else if(a!='\0'){
                  res+=a;
                  linelen++;
                  if(linelen >= TTYWIDTH){res+="\n";linelen=0;}
              }
              if(classic&&hassound&&a!='\n'&&a!='\r'&&a!='\0'&&a!=' '){
                if(m!=null&&!m.isRunning())
                    MRMainFrame.playSound("teletype0");
                else
                    MRMainFrame.playSound("teletype"+((int)(Math.random()*3)));
              }
              break;
          case ASCII_TTY:
              res+=toASCII(w,ltrs);
              break;
          case BASE2_TTY:
              res+=niceformat(w,null,2,5);
              break;
          case BASE8_TTY:
              res+=niceformat(w, null, 8,5);
              break;
          case BASE10_TTY:
              res+=w;
              break;
          case BASE16_TTY:
              res+=niceformat(w, null, 4,5);
              break;
          default:
      }
      
      return res;
  }
  
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JButton btnClear;
  private javax.swing.JComboBox comboDisplay;
  private javax.swing.JComboBox comboSeparator;
  private javax.swing.JLabel jLabel1;
  private javax.swing.JLabel jLabel2;
  private javax.swing.JLabel jLabel4;
  private javax.swing.JLabel jLabel5;
  private javax.swing.JPanel jPanel1;
  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JTextArea txtaTeletypeOutput;
  // End of variables declaration//GEN-END:variables
  
}
